---
sidebar_position: 2
slug: /tutorials/detect-race-conditions/one-step-closer-to-real-usages/
description: Second iteration, make the test closer and detect even more race conditions
---

import { OneStepCloserToRealUsages } from './Playgrounds';

# One step closer to real usages

## Zoom on previous test

### What to schedule?

One approach to solve the problem we discussed earlier is to follow a common pattern that we recommend when integrating a scheduler into existing tests. This involves replacing the original occurrences of the asynchronous API with scheduled versions of it. In our case, we replaced the line of code:

```js
const queued = queue(call);
```

with:

```js
const queued = queue(s.scheduleFunction(call));
```

### What to wait?

Once we've replaced raw asynchronous API calls with scheduled versions, the next step is to wait for them to complete. There are several ways to achieve this, but the recommended approach is to use `waitFor` to wait for all queries to resolve:

```js
const queued = queue(s.scheduleFunction(call));
pendingQueries.push(queued(1).then((v) => seenAnswers.push(v)));
pendingQueries.push(queued(2).then((v) => seenAnswers.push(v)));
await s.waitFor(Promise.all(pendingQueries));
```

An alternative would have been to use `waitAll` instead of `waitFor` but it comes with a precise requirement: promises have to be already scheduled by the time we request the scheduler. In other words, if our code delays a little bit the call to `call`, the scheduler might not wait enough.

Given the fact that `call` being fired synchronously is not a requirement for our current function, we can relax the constraint in our test to make evolving this implementation easier.

A `waitAll` version of the code above would be:

```js
const queued = queue(s.scheduleFunction(call));
queued(1).then((v) => seenAnswers.push(v));
queued(2).then((v) => seenAnswers.push(v));
await s.waitAll();
```

## Towards next test

The current implementation of our test only involves running two calls, but there may be potential issues that arise when more calls are made. To capture these scenarios, we will update the test to run an arbitrary number of calls. This will allow us to detect race conditions on a wider range of scenarios, including those with 3, 4, or even more calls.

## Your turn!

<OneStepCloserToRealUsages />

:::info What to expect?
Your test should help us to detect a bug in our current implementation of `queue`.
:::

<details>
<summary>
Hint #1
</summary>

`fc.scheduler` alone will not be enough! You'll have to generate another entry to be able to properly control the number of calls to `call` function.

</details>

<details>
<summary>
Hint #2
</summary>

Some possible options for generating additional test scenarios include:

- Using `fc.integer({min: 1, max: 10})` to generate a variable `numCalls` that determines how many times to call `call`. It's important to set a maximal value via `max` to prevent an excessively high number of calls.
- Using `fc.array(fc.nat(), {minLength: 1})` to generate the list of calls to issue against `call`.
- Using `fc.func(fc.boolean())` to generate a function that determines when to stop issuing calls.

And there are plenty others…

</details>
